package com.lagou.goodshop.controller;

import com.lagou.goodshop.pojo.Goods;
import com.lagou.goodshop.service.GoodsService;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.api.RSemaphore;
import org.redisson.api.RedissonClient;
import org.redisson.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.connection.DefaultMessage;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @Authther: mrwu
 * @date:2021/5/15-05
 * @Description:com.lagou.goodshop.controller
 */
@Slf4j
@RestController
public class PhoneController {

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    RedissonClient redissonClient;
    @Autowired
    GoodsService goodsService;

    @Autowired
    RocketMQTemplate rocketMQTemplate;

    @Autowired
    RestTemplate restTemplate;

    //秒杀商品 id 为商品ID
    @GetMapping("/goods/skill")
    public String skilGoods(String id){
        //模拟高并发下需要进行集群部署
        //由于多个服务同时卖手机，所以需要分布式锁
        //利用redis 实现分布式锁
        //查询该商品信息
        Goods goods = restTemplate.getForObject("http://localhost:9001/goods?id="+id, Goods.class);
        if (goods!=null){
            goods.getCount();
            //设置信号量
            RSemaphore semaphore = redissonClient.getSemaphore("ac:goods:" + id);
            //设置信号量的大小，将需要秒杀的商品数量设置为信号量大小
            semaphore.trySetPermits(goods.getCount());
            //尝试获取一个凭证，如果获取到证明抢到
            if (semaphore.tryAcquire()){
                //发送rocktmq 消息进行订单业务处理 需要将用户信息，商品信息通过mq发送
                //此处利用uuid 生成一个用户ID
                String uuid = UUID.randomUUID().toString();
                //des 主题名称
               rocketMQTemplate.asyncSend("goods-skill", id+":"+uuid, new SendCallback() {
                   @Override
                   public void onSuccess(SendResult sendResult) {
                       log.info("发送成功"+ sendResult.toString());
                   }
                   @Override
                   public void onException(Throwable e) {
                       e.printStackTrace();
                   }
               });
               return "sucess";
            }
        }
        return "false";
    }
    //更新缓存 不设置value 默认缓存返回值结果
    @CachePut(key = "#goods.id",cacheNames = "goods")
    @PostMapping("/goods")
    public Goods addGoods( @RequestBody Goods goods){
        System.out.println(goods);
        boolean save = goodsService.save(goods);
        if (save){
           return goods;
        }
        return null;
    }

    @GetMapping("/goods/list")
    public List<Goods> searchGoods(){
       return   goodsService.list();
    }

    //设置缓存
    @Caching(
            cacheable = {
                    @Cacheable(unless="#result == null",cacheNames = "goods")
            }
    )

    @GetMapping("/goods")
    public  Goods getGoods(String id){
       log.info("参数是"+id);

        return goodsService.getById(id);
    }

    //beforeInvocation 方法调用前删除缓存 默认为false
    @CacheEvict(value = "goods",beforeInvocation = false)
    @GetMapping("/goods/del")
    public boolean delGoods(String id){
        return goodsService.removeById(id);
    }

    //需要限流此接口会操作数据库
    @GetMapping("/goods/shop")
    public int decGoods(String id){
       return  goodsService.decreUpdate(id);
    }

    @Cacheable("goodscount")
    @GetMapping("/goods/count")
    public int getGoodscount(String id){
        return goodsService.getById(id).getCount();
    }

}
